package com.xuzao.developer.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.xuzao.developer.enums.RedisResultEnum;
import com.xuzao.developer.jedis.RedisConnPool;
import com.xuzao.developer.tools.context.SpringContextExt;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;

import java.util.*;

@Slf4j
public class RedisUtil {


    private static RedisConnPool redisConnPool;




    static {
        redisConnPool = SpringContextExt.getBean(RedisConnPool.class);
    }


    /**
     * 释放资源
     *
     * @param jedis
     * @param
     */
    public static void returnResource(Jedis jedis) {
        if (jedis != null) {
            redisConnPool.recycle(jedis);
        }
    }

    public static boolean isExist(String key) {
        if (key == null || "".equals(key)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            return jedis.exists(key);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
            return false;
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 获取自增
     * @param key
     * @param seconds
     * @return
     */
    public static Long incr(String key,Integer seconds) {
        Long rtn = null;
        if (key == null || "".equals(key)) {
            return rtn;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            rtn = jedis.incr(key);
            if (null == seconds) {
                jedis.expire(key, seconds);
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return rtn;
    }

    /**
     * 获取对象
     */
    public static Object get(String key) {
        if (key == null || "".equals(key)) {
            return null;
        }
        Object obj = null;
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            if (!jedis.exists(key)) {
                return null;
            }
            obj = SerializeUtil.unserialize(jedis.get(key.getBytes()));
            return obj;
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
            return null;
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 存入对象
     */
    public static boolean set(String key, Object obj) {
        if (key == null || "".equals(key) || obj == null) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            jedis.set(key.getBytes(), SerializeUtil.serialize(obj));
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return true;
    }

    /**
     * 存入有失效时间的对象
     *
     * @param seconds 失效时间，单位：秒
     */
    public static String set(String key, Object obj, int seconds) {
        String result = null;
        if (key == null || "".equals(key) || obj == null || seconds < 0) {
            return result;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            result = jedis.set(key.getBytes(), SerializeUtil.serialize(obj));
            jedis.expire(key.getBytes(), seconds);
            return result;
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
            return result;
        } finally {
            returnResource(jedis);
        }
    }


    public static String set(String key, Object value, String nxxx, String expx, long time) {
        if (key == null || "".equals(key) || value == null || time < 0) {
            return RedisResultEnum.ERR.getCode();
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            return jedis.set(key.getBytes(), SerializeUtil.serialize(value), nxxx.getBytes(), expx.getBytes(), time);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return RedisResultEnum.ERR.getCode();
    }

    public static boolean hset(String key, String field, Object value) {
        if (key == null || "".equals(key) || field == null || "".equals(field) || value == null) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            Long id = jedis.hset(key.getBytes(), field.getBytes(),Base64Util.encodeByte(SerializeUtil.serialize(value)));
            if (null == id) {
                return false;
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
            return false;
        } finally {
            returnResource(jedis);
        }
        return true;
    }

    public static void hset(String key, String field, Object value, long seconds) {
        if (key == null || "".equals(key) || field == null || "".equals(field) || value == null) {
            return;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            jedis.set(key.getBytes(), field.getBytes(), Base64Util.encodeByte(SerializeUtil.serialize(value)), "EX".getBytes(), seconds);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
    }

    public static Object hget(String key, String field) {
        if (key == null || "".equals(key) || field == null || "".equals(field)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            byte[] obj = jedis.hget(key.getBytes(), field.getBytes());
            if (obj != null) {
                return SerializeUtil.unserialize(Base64Util.decodeByByte(obj));
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * 删除对象
     */
    public static void remove(String key) {
        if (key == null || "".equals(key)) {
            return;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            jedis.del(key);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
    }


    public static void hmset(String key, List<Long> pkList, List<?> ValList) {
        if (key == null || "".equals(key) || pkList == null || pkList.size() == 0 || ValList == null || ValList.size() == 0) {
            return;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            jedis.hmset(key.getBytes(), getMap(pkList, ValList));
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
    }

    public static void hmsetStr(String key, List<String> pkList, List<?> ValList) {
        if (key == null || "".equals(key) || pkList == null || pkList.size() == 0 || ValList == null || ValList.size() == 0) {
            return;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            jedis.hmset(key.getBytes(), getStrMap(pkList, ValList));
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
    }

    private static Map<byte[], byte[]> getMap(List<Long> pkList, List<?> valList) {
        Map<byte[], byte[]> map = new HashMap<byte[], byte[]>();
        for (int i = 0; i < pkList.size(); i++) {
            map.put(pkList.get(i).toString().getBytes(), Base64Util.encodeByte(SerializeUtil.serialize(valList.get(i))));
        }
        return map;
    }

    private static Map<byte[], byte[]> getStrMap(List<String> pkList, List<?> valList) {
        Map<byte[], byte[]> map = new HashMap<byte[], byte[]>();
        for (int i = 0; i < pkList.size(); i++) {
            map.put(pkList.get(i).toString().getBytes(), SerializeUtil.serialize(valList.get(i)));
        }
        return map;
    }


    public static List<Object> getAll(String key) {
        if (key == null || "".equals(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            Collection<byte[]> objs = jedis.hvals(key.getBytes());
            if (objs != null && !objs.isEmpty()) {
                List<Object> list = new ArrayList<Object>();
                for (byte[] obj : objs) {
                    list.add(SerializeUtil.unserialize(Base64Util.decodeByByte(obj)));
                }
                return list;
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return null;
    }

    public static List<String> getAllFiled(String key) {
        if (key == null || "".equals(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            Map<byte[], byte[]> objs = jedis.hgetAll(key.getBytes());
            if (objs != null && objs.size() > 0) {
                List<String> list = new ArrayList<>();
                for (byte[] obj : objs.keySet()) {
                    list.add(new String(obj));
                }
                return list;
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return null;
    }


    public static Boolean hremove(String key, String field) {
        if (key == null || "".equals(key) || field == null || "".equals(field)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            Long id = jedis.hdel(key.getBytes(), field.getBytes());
            if (null == id) {
                return false;
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return true;
    }

    public static void expire(String key, int time) {
        if (key == null || "".equals(key)) {
            return;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            jedis.expire(key.getBytes(), time);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
    }

    public static String set(String key, String value, String nxxx, String expx,
                             int time) {
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            return jedis.set(key, value, nxxx, expx, time);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return RedisResultEnum.ERR.getCode();
    }

    public static Object eval(String script, List<String> keys, List<String> args) {
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            return jedis.eval(script, keys, args);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return null;
    }

    public static String getString(String key) {
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            return jedis.get(key);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        } finally {
            returnResource(jedis);
        }
        return null;
    }

    public static Jedis getJedis(Jedis jedis) {
        if (jedis == null) {
            return redisConnPool.getConnection();
        }
        return null;
    }


    /**
     * 获取失效时间
     */
    public static Long getTtl(String key) {
        if (key == null || "".equals(key)) {
            return -2L;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            return jedis.ttl(key);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
            return -2L;
        } finally {
            returnResource(jedis);
        }
    }


    /**
     * 存入有失效时间的对象
     *
     * @param seconds 失效时间，单位：秒
     */
    public static boolean setnx(String key, Object obj, int seconds) {
        if (key == null || "".equals(key) || obj == null || seconds < 0) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            Long setnx = jedis.setnx(key.getBytes(), SerializeUtil.serialize(obj));
            if (1L==setnx) {
                jedis.expire(key.getBytes(), seconds);
                return true;
            }else {
                return false;
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
            return false;
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 存入有失效时间的转json存入
     *
     * @param seconds 失效时间，单位：秒
     */
    public static String setList(String key, List<String> list, Integer seconds) {
        String result = null;
        if (key == null || "".equals(key) || list == null || seconds < 0) {
            return result;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            String objs = JSON.toJSONString(list);
            result = jedis.set(key,objs);
            jedis.expire(key, seconds);
            return result;
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
            return result;
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 存没失效时间的
     * @param key
     * @param list
     * @return
     */
    public static String setList(String key, List<String> list) {
        String result = null;
        if (key == null || "".equals(key) || list == null ) {
            return result;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            String objs = JSON.toJSONString(list);
            result = jedis.set(key,objs);
            return result;
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
            return result;
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 获取集合
     * @param key
     * @return
     */
    public static  List<String> getList (String key) {
        if (key == null || "".equals(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis(jedis);
            if (!jedis.exists(key)) {
                return null;
            }
            String s = jedis.get(key);
            List<String> list = JSONArray.parseArray(s, String.class);
            return list;
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
            return null;
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 刷新key的有效时间
     * @param key
     * @param seconds   秒
     * @return
     */
    public static boolean refreshTime(String key , Integer seconds) {
        if (key == null || "".equals(key)  || seconds < 0) {
            return false;
        }

        Jedis jedis = null;
        jedis = getJedis(jedis);
        try {
            jedis.expire(key, seconds);
            return true;
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
            return false;
        } finally {
            returnResource(jedis);
        }
    }
}
